//AbstractScene
//Created 20/12/12
//Version 1.1
//Created By Daniel Bowler
//
//AbstractScene is an pure abstract class that each demo scene will inherit from.
//This will allow the SceneManager class to hold a vector of AbstractScene pointers.
//
//Constructor should be used to init a scenes data - AllocateDynamicData
//should be where you use the new operator to create all your wonderful
//dynamic data. 
//When you transition to a new scene, call the current scenes DeallocDynamicData()
//first, then change the pointer, then call AllocDynamicData. 
//
//Only delete a scene once you close the application. 
//
//NOTE: We MUST make sure we are safely using pointers. For every single
//scene, ensure that we are both setting all pointers to NULL in the constructor
//and ensuring that we test for null before deleting dynamic data and then
//setting it back to NULL after deleting. As it turns out, my scene loading &
//unloading method can result in a scene having its DeallocateDynamicData
//function called even if the scene has not had its AllocateDynamicData
//function called before hand. The best way to prevent horrible crashes
//when the SceneManager is released (When the game is closed), is to ENSURE
//YOU USE POINTERS SAFELY. 
//
//Modified 03/07/13 - Each scene will have its own camera (creating/deletion
//handled by this class). Up untill scene 20(CameraScene), we wont actually use
//it. 
//
//Modified 06/07/13 - Default functionality for camera added - thus, you can
//do something like this inside your overriden UpdateWithDelta() function : 
//AbstractScene::UpdateWithDelta(delta) to move the camera. 

#pragma once

//#includes are here so that subclasses inherit them - makes life easy.
#include <string>
#include "GeometryGenerator.h"
#include "GraphicsInterface.h"
#include "Globals.h"
#include "RenderStates.h"
#include "VirtualCamera.h"
#include "xnacollision.h"
#include "d3dUtil.h"

//Include model types so they are usable by subclasses
#include "StaticModel.h"
#include "StaticInstancedModel.h"
#include "AnimatedModel.h"
#include "AbstractAdvancedModel.h"

//Include 2D rendering classes
#include "FontSheet.h"
#include "SpriteBatch.h"

//Also need access to the collision manager
#include "CollisionManager.h"

//Standard values for the camera frustum properties
#define DEFAULT_CAMERA_FRUSTUM_FOVY 0.25f*MathHelper::Pi
#define DEFAULT_CAMERA_FRUSTUM_NEARZ 1.0f

//Far Z depends on if fog is enabled. 
#define DEFAULT_CAMERA_FRUSTUM_FARZ 16000.0f //No heavy fog (Blue haze)
//#define DEFAULT_CAMERA_FRUSTUM_FARZ 850.0f  //>= Fog Range + Fog Start as defined in TileForwardFogGlobals.fx (Grey fog)

//Multiplier that affects the speed the camera moves. 
#define CAMERA_SPEED_MULTIPLER 25.0f // 25.0f for debug - 1.0f for release (Depends on game of course) 

class AbstractScene
{
public:
	//Constructor - will init scene title and grab a reference to the
	//D3DApp so that all scenes have a pointer to the sharedApplication
	AbstractScene();
	//Pure virtual function - so that no instance of AbstractScene can be
	//created. 
	virtual ~AbstractScene() = 0;

	//Virtual functions for initilising and then deleting dynamic data
	virtual void OpenScene() = 0;
	virtual void CloseScene() = 0;

	//Called when we transition to a scene without reloading the GPU data - here
	//you will want to reset lighting and active skydome.
	//
	//Default does nothing. 
	virtual void OnSceneReset();

	//Virtual functions to be overriden for rendering and updating
	virtual void UpdateWithDelta(float delta) = 0;
	virtual void RenderScene() = 0;

	//Virtual functions for mouse input. The D3DApp will forward mouse input
	//(obtained using the windows messaging system - In a proper game I would
	//implement Xinput/DirectInput but for the demo application, this method
	//will work fine)to the scene manager which in turn forwards the input
	//to the currentScene)
	//
	//Original message can tell us which mouse button has been pressed
	virtual void OnMouseDown(WPARAM btnState, int x, int y, UINT originalMessage) = 0;
	virtual void OnMouseUp(WPARAM btnState, int x, int y, UINT originalMessage) = 0;
	virtual void OnMouseMove(WPARAM btnState, int x, int y) = 0;

	//Virtual function which is called whenever the main window is resized. 
	//Some scenes may require the new aspect ratio for rendering
	virtual void OnResize() = 0;

	//Set the scene title - the scene title maybe used in the main window
	//caption within D3DApp. SceneManager will set the title
	//using this function
	void SetTitle(std::wstring title);

	//Returns the title. 
	inline std::wstring ReturnSceneTitle() { return sceneTitle;};
protected:
	//Pointer to our shared graphics interface - what the programmer interacts
	//with to render objects. 
	GraphicsInterface* sharedGraphicsInterface;

	//Game manager classes - such as the collision manager used to perform collision
	//detection
	CollisionManager* sharedCollisionManager;

	//Pointer to a virtual camera.
	VirtualCamera* camera;
	//Last mouse position - used when rotating the camera
	POINT lastMPos;

	//Scene title string. 
	std::wstring sceneTitle;

	//Default functions to control the camera.
	void ControlCameraTranslationsKeyboard(float delta);
	//For mouse - called in OnMouseMove() inside your scenes.
	void ControlCameraRotationsMouse(WPARAM btnState, int x, int y, POINT &lastMousePosition);

private:
	//Disable copy constructor and assignment. 
	AbstractScene(const AbstractScene &other);
	AbstractScene& operator = (const AbstractScene &other);
};